/**
 * Virtual Pager JavaScript Client Library
 * 
 * 
 * @author  Don Ross
 * @date	3/23/2012
 * @see {@link http://code.google.com/p/vpager/}
 * 
 */

/*
 * Utility methods to assist with OOP stuff
 */
Function.prototype.inheritsFrom = function( parentClassOrObject ){ 
	if ( parentClassOrObject.constructor == Function ) 
	{ 
		//Normal Inheritance 
		this.prototype = new parentClassOrObject();
		this.prototype.constructor = this;
		this.prototype.parent = parentClassOrObject.prototype;
	} 
	else 
	{ 
		//Pure Virtual Inheritance 
		this.prototype = parentClassOrObject;
		this.prototype.constructor = this;
		this.prototype.parent = parentClassOrObject;
	} 
	return this;
};

/*
 * ***************************
 * Core vPager API Starts Here
 * ***************************
 */

var VPAGER = {
		VERSION:				'0.1.3',
		ERR_GRP_PAGE_ADD:		10,
		ERR_GRP_PAGE_CANCEL:	20,
		ERR_GRP_PAGE_MOD:		30,
		ERR_GRP_PAGE_GET:		40,
		ERR_GRP_DISPLAY:		50
};

VPAGER.Util = function() {
	
	this.isAlphanumeric = function(string) {
		return string.match(/^[A-Za-z0-9]+$/);
	};
	
	this.isNumeric = function(string) {
		return string.match(/^[0-9]+$/); 
	};	
}();

VPAGER.Exception = function(name, message) {
	this.name = name;
	this.message = message;
};

VPAGER.Exception.prototype.ValidationError = function(message) {
	return new VPAGER.Exception("ValidationError", message);
};

VPAGER.Exception.prototype.DeserializationError = function(message) {
	return new VPAGER.Exception("DeserializationError", message);
};

VPAGER.Exception.prototype.IllegalParameters = function(message) {
	return new VPAGER.Exception("IllegalParameters", message);
};

VPAGER.Exception.prototype.ServiceRequestError = 
	function(message, status, error, err_prefix) {
		err_prefix = err_prefix || 0;
		var sre = new VPAGER.Exception("ServiceRequestError", message);
		sre.webStatus = status;
		sre.webError = error;
		sre.errorCode = err_prefix * 1000 + status;
		return sre;
};

VPAGER.Logging = function () {
	var mLogger = null;
	var mEnabled = false;
	
	if (arguments.callee._instance) {
		return arguments.callee._instance;
	} else {
		// Initialization
		arguments.callee._instance = this;
	}
	
	this.setLogger = function(logger) {
		if (typeof logger.log == 'function') {
			mLogger = logger;
			this.setEnabled(true);
		}
	};
	
	this.setEnabled = function(enabled) {
		if (enabled === true && mLogger) {
			mEnabled = true;
			this.log("VPAGER API Logging ENABLED [Version " + 
					  VPAGER.VERSION + "].");
		} else {
			mEnabled = false;
		}
	};
	
	this.isEnabled = function() {
		return ((mLogger !== null) && mEnabled);
	};
	
	this.getLogger = function() {
		return mLogger;
	};
	
	this.log = function(msg) {
		if (this.isEnabled()) {
			mLogger.log(msg);
		}
	};
	
	return this;
};

/**
 * Constructor for a high level object contain results of a web operation to server
 * @param {Object} JSON Data Returned by Server
 * @param {Number} The HTTP Status Code
 * @param {Object} The Error object resulting from Web call
 * @return {VPAGER.WebResult} Returns the created object
 * @since 1.0
 */
VPAGER.WebResult = function(data, status, error) {
	var mData = data;
	var mStatus = status;
	var mError = error;

	return {
		/**
		 * @return true if server returned a success status
		 */
		success : function() {
			return (mStatus < 300 && mStatus > 0 && !mError);
		},
		/**
		 * @return JSON data object returned by Server
		 */
		getData : function() {
			return mData;
		},
		/**
		 * @return HTTP status of server operation
		 */
		getStatus : function() {
			return mStatus;
		},
		/**
		 * @return Error object
		 */
		getError : function() {
			return mError;
		}
	};
	
};

VPAGER.DataElement = function(properties) {
	var mData = properties || {};

	this.toProperties = function() {
		return mData;
	};
	
	/**
	 * Return properties in a JSON formatted string suitable for serialization
	 * 
	 * @returns {String} Object Properties as JSON Formatted String
	 */
	this.toJSON = function() {
		return JSON.stringify(this.toProperties());
	};

	/**
	 * Abstract Methods 
	 */

	this.validateDeserialization = function() {
		throw "Abstract method [validateDeserialization] not implemented.";
	};
};
VPAGER.DataElement.deserialize = function(type, serializedData) {
	var item = new type(serializedData);
	item.validateDeserialization();
	return item;
};



/**
 * Returns a ServiceStatus object
 * 
 * @constructor
 * 
 * @param {Object} dataObj - Data Object backing the ServiceStatus
 * @since 1.0
 */
VPAGER.ServiceStatus = function (dataObj) {
	VPAGER.DataElement.call(this, dataObj);
	
	this.getOverallStatus = function() {
		return this.toProperties().OverallStatus;
	};

	this.getNetworkStatus = function() {
		return this.toProperties().NetworkStatus;
	};

	this.getDisplayState = function() {
		return this.toProperties().DisplayState;
	};

	this.getDisplayMode = function() {
		return this.toProperties().DisplayMode;
	};
	
	this.sameAs = function(other) {
	    return (
	        other && other instanceof VPAGER.ServiceStatus &&
            this.getOverallStatus() === other.getOverallStatus() &&
            this.getNetworkStatus() === other.getNetworkStatus() &&
            this.getDisplayState() === other.getDisplayState() &&
            this.getDisplayMode() === other.getDisplayMode() );
	};

};
VPAGER.ServiceStatus.inheritsFrom(VPAGER.DataElement);

/*
 * ServiceInfo
 */
VPAGER.ServiceInfo = function (dataObj) {
	VPAGER.DataElement.call(this, dataObj);
	var mStatus = new VPAGER.ServiceStatus(dataObj.Status);
	
	this.getStatus = function() {
		return mStatus;
	};
	
	this.getUpTime = function() {
		return this.toProperties().UpTime;
	};

	this.getServiceAPIVersion = function() {
		return this.toProperties().ServiceAPIVersion;
	};

};
VPAGER.ServiceInfo.inheritsFrom(VPAGER.DataElement);

/*
 * DisplayParams
 */
VPAGER.DisplayParams = function (dataObj) {
	VPAGER.DataElement.call(this, dataObj);
	
	this.getViewState = function() {
		return this.toProperties().ViewState;
	};
	
	this.setViewState = function(value) {
		this.toProperties().ViewState = value;
	};
	
	this.getForceDisable = function() {
		return this.toProperties().ForceDisable;
	};

	this.setForceDisable = function(value) {
		this.toProperties().ForceDisable = value;
	};

};
VPAGER.DisplayParams.inheritsFrom(VPAGER.DataElement);

/*
 * PageItem
 */
VPAGER.PageItem = function(dataObj) {

	VPAGER.DataElement.call(this, dataObj);
	
	// Property "Type" is read-only
	this.getType = function() {
		return this.toProperties().Type;
	};
	
	// Property "ID" is read-only
	this.getID = function() {
		return this.toProperties().ID;
	};
	
	// Property "CreationTime" is read-only
	this.getCreationTime = function() {
		/*		
		 * Convert date from serialized format into JS Date
		 * Serialized format from server is "\/Date(n)\/"
		 * Here 'n' represents number of milliseconds since Epoch
		 * The substr function takes out the "\/Date(" part, 
		 * and the parseInt function gets the integer and ignores 
		 * the ")\/" at the end. The resulting number is passed 
		 * into the Date constructor.
		*/		
		var serialDate = this.toProperties().CreationTime;
		return new Date(parseInt(serialDate.substr(6), 10));
	};
	
	// Property "Tag" is read-write
	this.getTag = function() {
		return this.toProperties().Tag;
	};

	this.setTag = function(value) {
		this.toProperties().Tag = value;
	};

	// Property "Source" is read-only
	this.getSource = function() {
		return this.toProperties().Source;
	};
	
	/**
	 * Abstract Methods
	 */
};

// PageItem Static Methods.
VPAGER.PageItem.inheritsFrom(VPAGER.DataElement);
VPAGER.PageItem.validateDeserialization = function() {
	
	// Next check more complete validation
	var id = this.getID();
	if (! (id && 
		   !isNaN(id) &&
		   id > 0))
	{
		throw new VPAGER.Exception().ValidationError("Page ID must be Numeric");
	}
};
// TODO: Consider converting all public methods to .prototype. convention
VPAGER.PageItem.prototype.sameAs = function(otherPage) {
    return (otherPage && 
            otherPage.getID instanceof Function &&
            this.getID() === otherPage.getID());
};




/*
 * ParentPage
 */
VPAGER.ParentPage = function(dataObj) {
	VPAGER.PageItem.call(this, dataObj);
	
	this.toProperties().Type = "Parent";
	
	// Property "Code" is read-only  
	this.getCode = function() {
		return this.toProperties().Code;
	};
	
	// Property "Location" is read-write
	this.getLocation = function() {
		return this.toProperties().Location;
	};
	
	this.setLocation = function(value) {
		this.toProperties().Location = value;
	};
	
	// Property "IsUrgent" is read-write
	this.getIsUrgent = function() {
		return this.toProperties().IsUrgent;
	};

	this.setIsUrgent = function(value) {
		this.toProperties().IsUrgent = value;
	};
	
	this.exactSameAs = function(otherPage) {
	    return ( this.parent.sameAs.call(this, otherPage) &&
                 this.getLocation() === otherPage.getLocation() &&
                 this.getIsUrgent() === otherPage.getIsUrgent() );
	};
	
	this.validateDeserialization = function() {
		// Call parent's method first, which will call our validate method
		VPAGER.PageItem.validateDeserialization.call(this);
		
		// Next check ParentPage specific validation
		// TODO
	};
	
};
VPAGER.ParentPage.inheritsFrom(VPAGER.PageItem);

VPAGER.DisplayHandler = function(serverProxy) {
	var proxy = serverProxy;
	
	var VIEW_ENABLED = 'ENABLED';
	var VIEW_DISABLED = 'DISABLED';

	this.getCurrentPage = function() {
	    return proxy.getDisplayCurrentPage();
	};
	
	this.isDisplayEnabled = function() {
	    return (proxy.getServiceInfo()
	                   .getStatus().getDisplayState() === VIEW_ENABLED);
	};
	
    this.enableDisplay = function() {
        var params = new VPAGER.DisplayParams();
        params.setViewState(VIEW_ENABLED);
        proxy.setDisplayParams(params);
    };
    
    this.disableDisplay = function(force) {
        var params = new VPAGER.DisplayParams();
        params.setViewState(VIEW_DISABLED);
        params.setForceDisable(force);
        proxy.setDisplayParams(params);
    };
    
};

VPAGER.EventPublisher = function() {
	var mListeners = {};
	
	function markEventType(type) {
		return ("vp_" + type).toUpperCase();
	}
	
	this.registerListener = function(eventType, listener) {
		// Protect against empty strings or reserved keywords, etc.
		eventType = markEventType(eventType);
		if (listener && 
			listener.onVPagerEvent instanceof Function)
		{
			if (!mListeners[eventType]) {
				mListeners[eventType] = [];
			}
			if (mListeners[eventType].indexOf(listener) < 0) {
				mListeners[eventType].push(listener);
			}
		}
	};
	
	this.deregisterListener = function(eventType, listener) {
		// Protect against empty strings or reserved keywords, etc.
		eventType = markEventType(eventType);
		if (listener)
		{
			if (mListeners[eventType]) {
				var idx = mListeners[eventType].indexOf(listener);
				if (idx >= 0) {
					mListeners[eventType].splice(idx,1);
				}
			}
		}
	};
	
	this.hasListener = function(eventType, listener) {
	    eventType = markEventType(eventType);
		return (mListeners[eventType] &&
		        mListeners[eventType].indexOf(listener) > -1);
	};
	
	this.publishEvent = function(eventType, event) {
		// Protect against empty strings or reserved keywords, etc.
		var markedEvent = markEventType(eventType);
		if (mListeners[markedEvent]) {
			mListeners[markedEvent].forEach(
					function(listener, idx, array) {
						listener.onVPagerEvent(eventType, event);
					});
		}
	}; 
	
	this.getListenerCount = function(eventType) {
	    var cnt = 0;
        eventType = markEventType(eventType);
        if (mListeners[eventType]) {
            cnt = mListeners[eventType].length;
        }
	    return cnt;
	};
};

VPAGER.MonitorBase = function() {
    var me = this;
    var mEnabled = false;
    var mRefreshRate = 3;
    var mProxy = undefined;
    var mTimer = undefined;
    var mCurrentData = undefined;
    var mLogger = undefined;

    var mProxyMethod = undefined;
    var mChangedEvent = undefined;
    var mErrorEvent = undefined;
    var mLogLabel = undefined;
    
    this.initialize = function(params) {
        me = params.context;
        mProxyMethod = params.method;
        mLogger = VPAGER.Logging();
        mProxy = new VPAGER.ServerProxy();
        if (me && mProxyMethod) {
            mChangedEvent = params.changeEvent || "DEF_EVENT";
            mErrorEvent = params.errorEvent || "ERR_EVENT";
            mLogLabel = params.logLabel || "VPAGER.MonitorBase";
        } else {
            throw VPAGER.Exception.IllegalParameters("Params 'context and 'method' required.");
        }
    };
    
    function checkForDataChanges() {
        var newData = undefined;
        
        try {
            newData = mProxy[mProxyMethod]();
            newData = me.prepareData(newData);
            if (me.dataHasChanged(mCurrentData, newData)) {
                mCurrentData = newData;
                me.publishEvent(mChangedEvent, mCurrentData);
            }
        } catch (e) {
            mLogger.log(mLogLabel + ": " + e.message);
            me.publishEvent(mErrorEvent, e);
        }
    }
    
    this.prepareData = function(data) {
        return data;
    };
    
    this.updateTimer = function() {
        if (this.isEnabled() && 
            this.getListenerCount(mChangedEvent) > 0 &&
            !this.isRunning())
        {
            checkForDataChanges();
            mTimer = setInterval(checkForDataChanges, mRefreshRate * 1000);
        } else if (!this.isEnabled() ||
                   this.getListenerCount(mChangedEvent) === 0)
        {
            if (mTimer) {
                clearInterval(mTimer);
                mTimer = undefined;
            }   
        }
    };

    this.disable = function() {
        mEnabled = false;
        this.updateTimer();
    };
    
    this.enable = function() {
        mEnabled = true;
        this.updateTimer();
    };
    
    this.isEnabled = function() {
        return mEnabled;
    };
    
    this.isRunning = function() {
        return (mTimer !== undefined);
    };
    
    this.getData = function() {
        return mCurrentData;
    };
    
    this.setRefreshRate = function(seconds) {
        if (seconds > 0) {
            mRefreshRate = seconds;
        }
    };
    
    this.getRefreshRate = function () {
        return mRefreshRate;
    };
    
    this.refresh = function() {
        checkForDataChanges();
    };
    
    this.registerChangeListener = function(listener) {
        this.registerListener(mChangedEvent, listener);
        this.updateTimer();
    };

    this.deregisterChangeListener = function(listener) {
        this.deregisterListener(mChangedEvent, listener);
        this.updateTimer();
    };

    this.registerErrorHandler = function(handler) {
        this.registerListener(mErrorEvent, handler);
    };

    this.deregisterErrorHandler = function(handler) {
        this.deregisterListener(mErrorEvent, handler);
    };
};
VPAGER.MonitorBase.inheritsFrom(VPAGER.EventPublisher);

VPAGER.PageMonitor = function() {
    var me = this;
    
    this.EVENT_CHANGE = "PAGE_LIST";
    this.EVENT_ERROR = "PAGE_LIST_ERROR";
    this.LOG_LABEL = "VPAGER.PageMonitor";
    
    // me.initialize(me, EVENT_CHANGE, EVENT_ERROR, LOG_LABEL);
    me.initialize({
        context: me,
        method: "getPages",
        changeEvent: me.EVENT_CHANGE,
        errorEvent: me.EVENT_ERROR,
        logLabel: me.LOG_LABEL
    });
    
    this.dataHasChanged = function(oldList, newList) {
        oldList = oldList || [];
        newList = newList || [];
        return (newList && 
                newList instanceof Array &&
                ( newList.length != oldList.length ||
                  oldList.some(function(page, idx, array) {
                      return !page.exactSameAs(newList[idx]);
                  }) ));
     };
    
    this.getPages = function() {
        return me.getData();
    };
    
};
VPAGER.PageMonitor.inheritsFrom(VPAGER.MonitorBase);

VPAGER.StatusMonitor = function() {
    var me = this;
    
    this.EVENT_CHANGE = "SERV_STATUS";
    this.EVENT_ERROR = "SERV_STATUS_ERROR";
    this.LOG_LABEL = "VPAGER.StatusMonitor";
    
    me.initialize({
        context: me,
        method: "getServiceInfo",
        changeEvent: me.EVENT_CHANGE,
        errorEvent: me.EVENT_ERROR,
        logLabel: me.LOG_LABEL
    });
    
    this.dataHasChanged = function(oldInfo, newInfo) {
        // Only compare the Status object from the Info Object returned
        return ( 
            (!oldInfo && newInfo &&
                newInfo instanceof VPAGER.ServiceStatus) ||
            (oldInfo  && newInfo && 
                newInfo instanceof VPAGER.ServiceStatus &&
                !newInfo.sameAs(oldInfo) ) );
     };
    
    this.getStatus = function() {
        return me.getData();
    };
    
    this.prepareData = function(data) {
        if (data && data instanceof VPAGER.ServiceInfo) {
            data = data.getStatus();
        }
        return data;
    };
    
};
VPAGER.StatusMonitor.inheritsFrom(VPAGER.MonitorBase);

VPAGER.ServerProxy = function() {
	var mServiceURI = "";
	var logger = VPAGER.Logging();
    var mDisplayHandler = undefined;
    var mPageMonitor = undefined;
    var mStatusMonitor = undefined;

	if (arguments.callee._instance) {
		return arguments.callee._instance;
	} else {
		// Initialization
		arguments.callee._instance = this;
        mDisplayHandler = new VPAGER.DisplayHandler(this);
        mPageMonitor = new VPAGER.PageMonitor();
        mStatusMonitor = new VPAGER.StatusMonitor();
	}
	

	//
	// Private Functions
	//
	
	function handleWebError(result, message, err_prefix) {
		var status = -1;
		var error = null;
		
		if (result && !result.success()) {
			message = message ? message : "Server Request Failed.";
			status = result.getStatus();
			if (result.getError()) {
    			if (result.getError().xhr) {
    				error = result.getError().xhr.statusText;
    			} else {
    				error = result.getError().message;				
    			}
			} else {
			    error = "";
			}
		} else if (!result) {
			message = "Unspecified Server Invocation Error.";
			error = "";
		}
		
		if (error != null) {
			throw new VPAGER.Exception().ServiceRequestError(
					message, status, error, err_prefix);
		}
		
		return result;
	}
	
	function webCall(method, uri, data) {
		var _jsonObject = undefined;
		var _status = undefined;
		var _error = undefined;
		var dojoFn = undefined;
		
		if (method) {
			method = method.toUpperCase();
			switch(method) {
				case "GET":
					dojoFn = dojo.xhrGet;
					break;
				case "POST":
					dojoFn = dojo.xhrPost;
					break;
				case "PUT":
					dojoFn = dojo.xhrPut;
					break;
				case "DELETE":
					dojoFn = dojo.xhrDelete;
					break;
			}
		}
		
		if (!dojoFn) {
			throw new VPAGER.Exception().IllegalParameters("Illegal Web Method specified.");
		}
		
		var jsonData = "{}";
		if (data) {
			if (typeof data === 'string') {
				jsonData = data;
			} else if (typeof data.toJSON === 'function') {
				jsonData = data.toJSON();
			}
		}
		logger.log("Invoking HTTP " + method + " on: " + mServiceURI + uri);
		logger.log("         HTTP " + method + " Request data: " + jsonData);
		dojoFn({
			sync : true,
			url : mServiceURI + uri,
			postData: jsonData,
			handleAs : "json",
			headers: { "Content-Type": "application/json"},
			// The success handler
			load : function(jsonData, ioargs) {
				_jsonObject = jsonData;
				_status = ioargs.xhr.status;
			},
			// The error handler
			error : function(error, ioargs) {
				_error = error;
				_status = ioargs.xhr.status;
			}
		});
		
		// Determine any error and appropriate error message to log
		var errmsg =_error;
        if(_error) {
            if(_error.xhr) {
                errmsg = _error.xhr.statusText;
            } else {
                errmsg = _error.message;
            }
        }
		logger.log("HTTP " + method + " Status=" + _status + ", Error=" + errmsg);
		logger.log("HTTP " + method + " Response Data=" + JSON.stringify(_jsonObject));

		return new VPAGER.WebResult(_jsonObject, _status, _error);
	}

    function webGetCall(uri) {
        return webCall("GET", uri, undefined);
    }

    function webDeleteCall(uri) {
        return webCall("DELETE", uri, undefined);
    }

    function webPostCall(uri, data) {
        return webCall("POST", uri, data);
    }
    
    function webPutCall(uri, data) {
        return webCall("PUT", uri, data);
    }

	function getPageID(data) {
		var pageID = undefined;
		if (typeof data === "number" ) {
			pageID = data;
		} else if (data.getID instanceof Function){
			pageID = data.getID();
		} else {
			throw new VPAGER.Exception().IllegalParameters("Invalid Page ID");
		}
		return pageID;
	}
	
	function deserializePage(pageData) {
	    var page = undefined;
	    var pageType = undefined;
	    if (pageData instanceof Object && pageData.Type) {
	        switch (pageData.Type) {
	            case "Parent":
	               pageType = VPAGER.ParentPage;
	               break;
	            case "Driver":
	               // TODO: Add "Driver" page type when supported
	               break;
	            default:
	               break;
	        }
	        if (pageType) {
	            page = VPAGER.DataElement.deserialize(pageType, pageData);
	        }
	    }
	    
	    if (!page) {
            throw new VPAGER.Exception().DeserializationError(
                "Could not determine Page Type from server returned data.");

	    }
	    
	    return page;
	}
	
	//
	// Public Functions
	//
	
	this.initialize = function(params) {
		if (params && params instanceof Object) {
			if (params.serviceURI) {
				mServiceURI = params.serviceURI;
			} else {
				throw new VPAGER.Exception().IllegalParameters("serviceURI paramater is required.");
			}
		} else {
			throw new VPAGER.Exception().IllegalParameters("Invalid Parameter object.");
		}
	};

	this.getServiceURI = function() {
		return mServiceURI;
	};

	this.getServiceInfo = function() {
		var info = undefined;
		var wr = handleWebError(webGetCall('/info'), 
					            "Get Service Info Request Failed.");
		info = new VPAGER.ServiceInfo(wr.getData());
		logger.log("info=" + JSON.stringify(info));
		return info;
	};

	//
	// Page Related Functions
	//
	
	this.getPageByID = function(id) {
		var page = undefined;
		
		// id must be defined and a number (or parseable string)
		if (id && !(isNaN(id-0))) {
			var wr = handleWebError(webGetCall('/pages/id/' + id),
					                "Get Page Request Failed.",
					                VPAGER.ERR_GRP_PAGE_GET);
			page = deserializePage(wr.getData());
		} else {
			throw new RangeError("Must use a valid ID number.");
		}
		return page;
	};
	
	this.submitNewPage = function(pageRequest) {
		var submitURI = '';
		var pageType = undefined;
		
		// TODO: Add Driver Page Type
		if (pageRequest && pageRequest instanceof VPAGER.ParentPage) {
			submitURI = '/pages/type/parent';
			pageType = VPAGER.ParentPage;
		} else {
			throw new VPAGER.Exception().IllegalParameters("Invalid Page Object");
		}
		
		var wr = handleWebError(webPostCall(submitURI, pageRequest),
				                "Submit New Page Request Failed.",
				                VPAGER.ERR_GRP_PAGE_ADD);

		return deserializePage(wr.getData());
	};
	
	this.modifyPage = function(page) {
		var submitURI = '';
		var pageType = undefined;
		var pageID = getPageID(page);
		var rv = undefined;
		
		// TODO: Add Driver Page Type
		if (page && page instanceof VPAGER.ParentPage) {
			submitURI = '/pages/type/parent/';
			pageType = VPAGER.ParentPage;
		} else {
			throw new VPAGER.Exception().IllegalParameters("Invalid Page Object");
		}
		
		submitURI += pageID.toString();
		var wr = handleWebError(webPutCall(submitURI, page),
				                "Modify Page Request Failed.",
				                VPAGER.ERR_GRP_PAGE_MOD);
        return deserializePage(wr.getData());
	};
	
	this.cancelPage = function(page) {
		var submitURI = '/pages/id/';
		var pageID = getPageID(page);
		
		submitURI += pageID.toString();
		var wr = handleWebError(webDeleteCall(submitURI),
				                "Cancel Page Request Failed.",
				                VPAGER.ERR_GRP_PAGE_CANCEL);
		return wr.success();
	};
	
	this.cancelAllPages = function() {
		var submitURI = '/pages';
		
		var wr = handleWebError(webDeleteCall(submitURI),
				                "Cancel All Pages Request Failed.",
				                VPAGER.ERR_GRP_PAGE_CANCEL);

		// Return number of pages canceled
		return wr.getData();
	};
	
	this.getPages = function() {
		var pagesURI = '/pages';
		var pageList = [];
		
		var wr = handleWebError(webGetCall(pagesURI),
				                "Get All Pages Request Failed.",
				                VPAGER.ERR_GRP_PAGE_GET);
		pageList = wr.getData().map(function(pageData){
			return deserializePage(pageData);
		});

		return pageList;
	};

	//
	// Display Related Functions
	//
	
	this.getDisplayCurrentPage = function() {
		var submitURI = '/display/current';
		var wr = handleWebError(webGetCall(submitURI),
				                "Get Current Display Page Request Failed.",
				                VPAGER.ERR_GRP_DISPLAY);
		return deserializePage(wr.getData());
	};
	
	this.setDisplayParams = function(params) {
		var submitURI = '/display/params';
		
		handleWebError(webPutCall(submitURI, params),
				       "Set Display Params Request Failed.",
				       VPAGER.ERR_GRP_DISPLAY);
	};
	
    this.getDisplayHandler = function() {
        return mDisplayHandler;
    };

    this.getPageMonitor = function() {
        return mPageMonitor;
    };

    this.getStatusMonitor = function() {
        return mStatusMonitor;
    };


};
